package ac.github.os.internal.core.store

import ac.github.os.OriginSkill
import taboolib.common.LifeCycle
import taboolib.common.platform.Awake
import taboolib.common.platform.function.info
import taboolib.common5.Coerce
import java.util.concurrent.ConcurrentHashMap

class Store {

    companion object {

        var GLOBAL: Store? = null

        lateinit var storage: Storage

        @Awake(LifeCycle.LOAD)
        fun loadStorage() {
            val string = OriginSkill.config.getString("options.storage")
            storage = when (string) {
                "MYSQL", "MySQL", "SQL" -> StorageSQL()
                else -> StorageLocal()
            }
            storage.load()
            GLOBAL = storage.findStore()
        }

        fun save(string: String, data: Data) {
            storage.set(string, data)
        }
    }


    val map = ConcurrentHashMap<String, Data>()

    val usable: Map<String, Data>
        get() = map.filter { !it.value.isNull() }

    fun has(key: String): Boolean {
        return map.containsKey(key) && map[key]?.isNotNull() ?: false
    }

    fun set(key: String, data: Data) {

        if (this.map.containsKey(key) && data.isNull()) {
            map.remove(key)
            storage.remove(key)
        } else {
            map[key] = data
            storage.set(key, data)
        }

    }

    fun get(key: String): Data? {
        return if (has(key)) map[key] else null
    }

    class Data(private var value: String) {

        constructor(any: Any) : this(Coerce.toString(any))

        fun add(float: Float) {
            set(value.toBigDecimal().add(float.toBigDecimal()).toString())
        }

        fun subtract(float: Float) {
            set(value.toBigDecimal().subtract(float.toBigDecimal()).toString())
        }

        fun multiply(float: Float) {
            set(value.toBigDecimal().multiply(float.toBigDecimal()).toString())
        }

        fun division(float: Float) {
            set(value.toBigDecimal().divide(float.toBigDecimal()).toString())
        }

        fun set(string: String) {
            value = string
        }

        fun asDouble() = Coerce.toDouble(value)

        fun asBoolean() = Coerce.toBoolean(value)

        fun asLong() = Coerce.toLong(value)

        fun asInteger() = Coerce.toInteger(value)

        fun asFloat() = Coerce.toFloat(value)

        fun asString() = Coerce.toString(value)

        fun isNotNull() = !isNull()

        fun isNull() = value == "null"

    }

}